#!/usr/bin/env python
#coding=utf-8

import random
import rospy
import socket
import time
from paho.mqtt import client as paho_mqtt_client
import threading

from tool.log_parser import Log_Parser
log = Log_Parser()

class Mqtt_Client:

    def __init__(self, node_name):
        self.__node_name = node_name
        self.__host = self.GetLocalIP()

        self.__connected = False
        self.__index = 0
        # generate client ID with pub prefix randomly
        self.__client_id = "mqtt-client-{}".format(random.randint(0, 1000))
        self.__client = paho_mqtt_client.Client(self.__client_id)
        # self.__client_id = "mqtt-client-{}".format(random.randint(0, 1000))
        # self.__ConnectMqttServer()
        # elf.__client.loop_start()
        self.lock = threading.Lock()

    def __del__(self):
        self.CloseClient()

    def Connected(self):
        return self.__connected

    '''
    获取本机ip地址
    '''

    def GetLocalIP(self):
        return "127.0.0.1"

    def on_connect(self, client, userdata, flags, rc):
        """_summary_
        连接成功回调
        Args:
            client (_type_): _description_
            userdata (_type_): _description_
            flags (_type_): _description_
            rc (_type_): _description_

        Returns:
            _type_: _description_
        """
        self.__connected = True

        rospy.logwarn("on_connect MQTT [{}].".format(rc))
        logmsg = ("[{}][on_connect] MQTT [{}].".format(self.__node_name,rc))
        log.LogInfo(self.__node_name,logmsg)

    def on_disconnect(self, client, userdata, rc):
        '''
        断联有两种情况
        正常断开连接MQTT_ERR_SUCCESS (0)
        网络不正常断开连接 rc != 0
        '''
        rospy.logwarn("on_disconnect MQTT [{}].".format(rc))
        
        if rc != 0 :
            self.CloseClient()
            self.__client_id = "mqtt-client-{}".format(random.randint(0, 1000))
            self.__client = paho_mqtt_client.Client(self.__client_id)               # 创建客户端
            self.ConnectMqttServer_on_disconnect()
            logmsg = ("[{}][on_disconnect] MQTT [{}],client_id:[{}].".format(self.__node_name,rc,self.__client_id))
            log.LogInfo(self.__node_name,logmsg)
        else:
            self.__connected = False
            logmsg = ("[{}][on_disconnect] MQTT [{}].".format(self.__node_name,rc))
            log.LogInfo(self.__node_name,logmsg)


    def on_connect_fail(self, client, userdata):
        """_summary_
        连接失败
        Args:
            client (_type_): _description_
            userdata (_type_): _description_
        """
        rospy.logwarn("on_connect_fail MQTT ")
        logmsg = ("[{}] on_connect_fail MQTT ".format(self.__node_name))
        log.LogInfo(self.__node_name,logmsg)
        self.__connected = False

    '''
       mqtt_client连接操作
    '''

    def ConnectMqttServer(self):
        while not self.__connected:
        # if not self.__connected:
            rospy.loginfo("[{}]Connecting to MQTT Broker...".format(self.__node_name))
            logmsg = ("[{}]Connecting to MQTT Broker...".format(self.__node_name))
            log.LogInfo(self.__node_name,logmsg)
            try:
                # 
                self.__client.on_connect = self.on_connect
                self.__client.on_connect_fail = self.on_connect_fail
                self.__client.on_disconnect = self.on_disconnect
                self.__client.connect(self.__host, "1883", 1)
                self.__client.loop_start()
                self.__connected=True
            except Exception as err:
                rospy.loginfo("[{}]Connect to MQTT Broker fail.{}.".format(self.__node_name,err))
                logmsg = ("[{}]Connect to MQTT Broker fail.{}.".format(self.__node_name,err))
                log.LogInfo(self.__node_name,logmsg)
                self.__connected=False
            time.sleep(1)

    def ConnectMqttServer_on_disconnect(self):
        
            rospy.loginfo("[{}]Connecting to MQTT Broker...".format(self.__node_name))
            logmsg = ("[{}]Connecting to MQTT Broker...".format(self.__node_name))
            log.LogInfo(self.__node_name,logmsg)
            try:
                self.__client.on_connect = self.on_connect
                self.__client.on_connect_fail = self.on_connect_fail
                self.__client.on_disconnect = self.on_disconnect
                self.__client.connect(self.__host, "1883", 1)
                self.__client.loop_start()
                self.__connected=True
            except Exception as err:
                rospy.loginfo("[{}]Connect to MQTT Broker fail.{}.".format(self.__node_name,err))
                logmsg = ("[{}]Connect to MQTT Broker fail.{}.".format(self.__node_name,err))
                log.LogInfo(self.__node_name,logmsg)
                self.__connected=False

    '''
       mqtt_client关闭操作
    '''

    def CloseClient(self):
        # print("CloseClient")
        # if self.__connected:
        #     self.__connected = False
        #     self.__client.loop_stop()
        #     self.__client.disconnect()
        #     rospy.loginfo("[{}]Disonnected to MQTT Broker.".format(
        #         self.__node_name))
        print("------------------CloseClient------------------")
        self.__connected = False
        self.__client.loop_stop()
        self.__client.disconnect()
        print("[{}][CloseClient]Disonnected to MQTT Broker.".format(self.__node_name))
        logmsg = "[{}][CloseClient]Disonnected to MQTT Broker.".format(self.__node_name)
        log.LogInfo(self.__node_name,logmsg)

    '''
        转换时间到字符串
    '''

    def ConvertTime(self, secs):
        return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(secs))

    '''
        转换布尔量到数值
    '''

    def ConvertBool(self, bool):
        return 1 if bool else 0

    def dataAppendPlus(self, msg):
        """
        发送的索引自增
        _summary_
        """
        self.__index += 1
        if (self.__index > 10000000):
            self.__index = 0
        msg["index"] = self.__index

    '''
       mqtt_client发布话题
    '''

    def PublishTopic(self, topic, msg, qos=0, retain=False):
        if self.__connected:
            # 先要获取锁
            self.lock.acquire()
            try:
                # 修改
                topic_ = "/out/{}".format(topic)
                result = self.__client.publish(topic_, msg, qos, retain)
            finally:
                # 改完了一定要释放锁
                self.lock.release()
                status = result[0]
                if status != 0:
                    rospy.logerr("[{}]mqtt Failed to send message to topic {}".format(self.__node_name, topic))
                    logmsg = ("[{}]mqtt Failed to send message to topic {}".format(self.__node_name, topic))
                    log.LogInfo(self.__node_name,logmsg)
                else:
                    # rospy.loginfo(
                    #     "[{}]mqtt Success to send message to topic {}".format(
                    #         self.__node_name, topic))
                    pass
                return status
